<!DOCTYPE html>
<html lang="en">
<head>
    <title>让爱随心而动</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body {
            font-family: Monospace;
            background-color: #f0f0f0;
            margin: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>

<script src="js/nb.js"></script>

<script src="js/Projector.js"></script>
<script src="js/CanvasRenderer.js"></script>

<script src="js/tween.min.js"></script>
<script src="js/Sparks.js"></script>

<!-- load the font file from canvas-text -->

<script src="js/helvetiker_regular.typeface.js"></script>

<script>

    var container;

    var camera, scene, renderer;

    var group, text, plane;

    var targetRotation = 0;
    var targetRotationOnMouseDown = 0;

    var mouseX = 0;
    var mouseXOnMouseDown = 0;

    var windowHalfX = window.innerWidth / 2;
    var windowHalfY = window.innerHeight / 2;

    var heartShape, particleCloud, sparksEmitter, emitterPos;
    var _rotation = 0;
    var timeOnShapePath = 0;

    init();
    animate();

    function init() {

        container = document.createElement('div');
        document.body.appendChild(container);


        //相机
        camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
        camera.position.set(0, 150, 800);

        //场景
        scene = new THREE.Scene();

        group = new THREE.Group();
        scene.add(group);

        // Get text from hash

        var string = "LOVE U";
        var hash = document.location.hash.substr(1);

        if (hash.length !== 0) {

            string = hash;

        }

        var text3d = new THREE.TextGeometry(string, {

            size: 80,
            height: 20,
            curveSegments: 2,
            font: "helvetiker"

        });

        text3d.computeBoundingBox();
        var centerOffset = -0.5 * (text3d.boundingBox.max.x - text3d.boundingBox.min.x);

        var textMaterial = new THREE.MeshBasicMaterial({color: Math.random() * 0xffffff, overdraw: 0.5});

        text = new THREE.Mesh(text3d, textMaterial);

        // Potentially, we can extract the vertices or faces of the text to generate particles too.
        // Geo > Vertices > Position

        text.position.x = centerOffset;
        text.position.y = 100;
        text.position.z = 0;

        text.rotation.x = 0;
        text.rotation.y = Math.PI * 2;

        group.add(text);


        particleCloud = new THREE.Object3D(); // Just a group
        particleCloud.y = 800;
        group.add(particleCloud);

        // Create Particle Systems

        // Heart

        var x = 0, y = 0;

        heartShape = new THREE.Shape();

        heartShape.moveTo(x + 25, y + 25);
        heartShape.bezierCurveTo(x + 25, y + 25, x + 20, y, x, y);
        heartShape.bezierCurveTo(x - 30, y, x - 30, y + 35, x - 30, y + 35);
        heartShape.bezierCurveTo(x - 30, y + 55, x - 10, y + 77, x + 25, y + 95);
        heartShape.bezierCurveTo(x + 60, y + 77, x + 80, y + 55, x + 80, y + 35);
        heartShape.bezierCurveTo(x + 80, y + 35, x + 80, y, x + 50, y);
        heartShape.bezierCurveTo(x + 35, y, x + 25, y + 25, x + 25, y + 25);

        var hue = 0;

        var hearts = function (context) {

            context.globalAlpha = 0.5;
            var x = 0, y = 0;
            context.scale(0.05, -0.05); // Scale so canvas render can redraw within bounds
            context.beginPath();
            // From http://blog.burlock.org/html5/130-paths
            context.bezierCurveTo(x + 2.5, y + 2.5, x + 2.0, y, x, y);
            context.bezierCurveTo(x - 3.0, y, x - 3.0, y + 3.5, x - 3.0, y + 3.5);
            context.bezierCurveTo(x - 3.0, y + 5.5, x - 1.0, y + 7.7, x + 2.5, y + 9.5);
            context.bezierCurveTo(x + 6.0, y + 7.7, x + 8.0, y + 5.5, x + 8.0, y + 3.5);
            context.bezierCurveTo(x + 8.0, y + 3.5, x + 8.0, y, x + 5.0, y);
            context.bezierCurveTo(x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5);
            context.fill();
            context.lineWidth = 0.5; //0.05
            context.stroke();

        }

        var setTargetParticle = function () {

            var material = new THREE.SpriteCanvasMaterial({
                program: hearts
            });

            material.color.setHSL(hue, 1, 0.75);
            hue += 0.001;
            if (hue > 1) hue -= 1;

            particle = new THREE.Sprite(material);

            particle.scale.x = particle.scale.y = Math.random() * 40 + 40;
            particleCloud.add(particle);

            return particle;

        };

        var onParticleCreated = function (p) {

            p.target.position.copy(p.position);

        };

        var onParticleDead = function (particle) {

            particle.target.visible = false;
            particleCloud.remove(particle.target);

        };

        sparksEmitter = new SPARKS.Emitter(new SPARKS.SteadyCounter(160));

        emitterpos = new THREE.Vector3();

        sparksEmitter.addInitializer(new SPARKS.Position(new SPARKS.PointZone(emitterpos)));
        sparksEmitter.addInitializer(new SPARKS.Lifetime(0, 2));
        sparksEmitter.addInitializer(new SPARKS.Target(null, setTargetParticle));

        sparksEmitter.addInitializer(new SPARKS.Velocity(new SPARKS.PointZone(new THREE.Vector3(0, -50, 10))));

        // TOTRY Set velocity to move away from centroid

        sparksEmitter.addAction(new SPARKS.Age());
        //sparksEmitter.addAction(new SPARKS.Accelerate(0.2));
        sparksEmitter.addAction(new SPARKS.Move());
        sparksEmitter.addAction(new SPARKS.RandomDrift(50, 50, 2000));

        sparksEmitter.addCallback("created", onParticleCreated);
        sparksEmitter.addCallback("dead", onParticleDead);
        sparksEmitter.addCallback("updated", function (particle) {

            particle.target.position.copy(particle.position);

        });

        sparksEmitter.start();

        // End Particles


        renderer = new THREE.CanvasRenderer();
        renderer.setClearColor(0xf0f0f0);
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        container.appendChild(renderer.domElement);

        document.addEventListener('mousedown', onDocumentMouseDown, false);
        document.addEventListener('touchstart', onDocumentTouchStart, false);
        document.addEventListener('touchmove', onDocumentTouchMove, false);

        //

        window.addEventListener('resize', onWindowResize, false);

    }

    function onWindowResize() {

        windowHalfX = window.innerWidth / 2;
        windowHalfY = window.innerHeight / 2;

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(window.innerWidth, window.innerHeight);

    }

    //

    document.addEventListener('mousemove', onDocumentMouseMove, false);

    function onDocumentMouseDown(event) {

        event.preventDefault();

        mouseXOnMouseDown = event.clientX - windowHalfX;
        targetRotationOnMouseDown = targetRotation;

        if (sparksEmitter.isRunning()) {

            sparksEmitter.stop();

        } else {

            sparksEmitter.start();

        }

    }

    function onDocumentMouseMove(event) {

        mouseX = event.clientX - windowHalfX;

        targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;

    }

    function onDocumentTouchStart(event) {

        if (event.touches.length == 1) {

            event.preventDefault();

            mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;
            targetRotationOnMouseDown = targetRotation;

        }

    }

    function onDocumentTouchMove(event) {

        if (event.touches.length == 1) {

            event.preventDefault();

            mouseX = event.touches[0].pageX - windowHalfX;
            targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05;

        }

    }

    //

    function animate() {//更新场景

        requestAnimationFrame(animate);

        render();

    }

    function render() {

        timeOnShapePath += 0.0337;

        if (timeOnShapePath > 1) timeOnShapePath -= 1;

        // TODO Create a PointOnShape Action/Zone in the particle engine
        var pointOnShape = heartShape.getPointAt(timeOnShapePath);

        emitterpos.x = pointOnShape.x * 5 - 100;
        emitterpos.y = -pointOnShape.y * 5 + 400;

        // Pretty cool effect if you enable this
        // particleCloud.rotation.y += 0.05;

        group.rotation.y += (targetRotation - group.rotation.y) * 0.05;
        renderer.render(scene, camera);
    }

</script>

</body>
</html>
